<template>
  <div class="approval-history-box">
    <div class="title">
      {{ t('log') }}
    </div>
    <a-timeline>
      <a-timeline-item>
        <template #dot>
          <span class="start"></span>
        </template>
        {{ t('start') }}
      </a-timeline-item>
      <div
          v-for="(approveTaskListGroupItem, index) in approveTaskListGroup"
          :key="index"
          :ref="
                    el => {
                        if (el) doms[`time-line-bottom-${i}`] = el
                    }
                "
          :class="{ group: approveTaskListGroupItem.children.length > 1 }"
      >
        <div v-if="approveTaskListGroupItem.children.length" class="group-mark"></div>
        <div
            v-for="(item, approveTaskIndex) in approveTaskListGroupItem.children"
            :class="`${
                        approveTaskIndex === approveTaskListGroupItem.children.length - 1
                            ? approveTaskListGroupItem.btnText
                                ? 'last-group-child-more'
                                : 'last-group-child'
                            : ''
                    }`"
            :key="approveTaskIndex"
        >
          <a-timeline-item>
            <template #dot>
              <div class="avatar">
                {{ item.assignUserName ? item.assignUserName[0] : item.assignUserName }}
              </div>
            </template>
            <div
                class="approval-history-content"
                :class="{
                                'end-style': item.assignResult === 'SUBMIT' && item.assignUserName === t('system')
                            }"
            >
              <h5 class="title">
                <img v-if="getIcon(item)" :src="getIcon(item)" class="status-icon" />
                {{ item.taskName }}-
                {{ item.assignUserName }}
              </h5>
              <p v-if="!isNullOrEmpty(item.lastModifiedDate)" class="time">
                {{ item.lastModifiedDate }}
              </p>
              <p v-if="item.assignRemark" class="comment">
                {{ item.assignRemark }}
              </p>
            </div>
          </a-timeline-item>
        </div>
        <a
            v-if="approveTaskListGroupItem.btnText"
            class="open"
            @click="setMoreOrLessHandler(approveTaskListGroupItem, index)"
        >{{ approveTaskListGroupItem.btnText }}</a
        >
      </div>
    </a-timeline>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, watch, nextTick, onBeforeUpdate } from 'vue'
import { useI18n } from 'vue-i18n'
import { isNullOrEmpty } from '@/utils/is'
import { formatDataType, approveTaskListItem, processTaskListItem } from '../types/index'
export default defineComponent({
  name: 'ApprovalHistory',
  props: {
    approveTaskList: {
      type: Array,
      default: () => []
    }
  },
  setup(props) {
    const { t } = useI18n()
    const doms = ref([])
    const approveTaskListGroup = ref<formatDataType[]>([])
    const max = ref(3) // 分组默认最大显示数据条数
    function formatData(groupItem: approveTaskListItem[]) {
      // 为显示的时间线数据增加字段,用于判断是否显示
      const groupItemData = groupItem.map(item => {
        item.title = getTitle(item)
        item.time = getInitStatus(item) ? item.endTime : item.beginTime
        item.comment = item.comment ? `${t(`comment`)}${t('colon')}${item.comment}` : ''
        return item
      })
      const newData: formatDataType = {
        originData: groupItemData, // 数据真正的长度
        children: groupItemData.slice(0, max.value) // 需要展示的数据的, 分组时, 默认最多展示3条
      }
      newData.btnText = getBtnText(newData)
      return newData
    }
    /**
     * 按钮展示的文本['收起', '展开']
     */
    function getBtnText(groupItemData) {
      if (groupItemData.originData.length <= max.value) {
        return ''
      }
      return groupItemData?.originData.length > groupItemData?.children.length ? t('openMore') : t('less')
    }
    /**
     * 流程是否是发起状态, 目前发起状态是null, 影响标题显示,时间显示
     */
    function getInitStatus(item) {
      return item.status
    }
    /**
     * 时间线,标题差异化显示
     */
    function getTitle(item) {
      let title = ''
      if (getInitStatus(item)) {
        // 流程中的状态
        title = `${item.taskName ? `${item.taskName} - ` : ''}${item.operatorName}`
      } else {
        // 初始状态
        title = `发起人 - ${item.operatorName}`
      }
      return title
    }
    /**
     * 对接口返回的数据根据字段approveNodeKey进行分组
     * 1. 要求按照数据的顺序进行分组
     * 2. 根据approveNodeKey分组
     * 因为流程日志有回退的情况,approveNodeKey不能完全实现分组的情况,后台控制确保数据的顺序
     * 相邻的数据根据approveNodeKey分组
     */
    function getApproveTaskListGroup() {
      // 用于生成新的二维数组
      const groupArr = [] as formatDataType[]
      // 用于判断是否是一组的Key
      let preKey = ''
      // 提前定义的每一小分组的数据
      let groupItem = [] as approveTaskListItem[]
      props.approveTaskList.forEach((approveTaskItem: approveTaskListItem, approveTaskItemIndex) => {
        // 开始节点，省略
        if (approveTaskItem.taskId.startsWith('startNode')) {
          return
        }
        // 结束节点，没有审批人的时候补充为系统
        if (approveTaskItem.taskId.startsWith('Event') && !approveTaskItem.assignUserName) {
          approveTaskItem.assignUserName = t('system')
        }

        if (approveTaskItem.taskId !== preKey) {
          groupArr.push(formatData(groupItem))
          groupItem = [approveTaskItem]
        } else {
          groupItem.push(approveTaskItem)
        }
        // 逻辑执行之后把当前的key赋值preKey用于下一个循环的判断
        preKey = approveTaskItem.taskId
      })
      // 循环完毕,把最后制作分组数据推入groupArr
      if (groupItem.length > 0) {
        groupArr.push(formatData(groupItem))
      }
      approveTaskListGroup.value = groupArr
      nextTick(() => {
        // 时间线最后一个元素滚动到可视区域
        const [groupRef] = doms.value[`time-line-bottom-${groupArr.length - 1}`] || []
        groupRef?.scrollIntoView()
      })
    }
    /**
     * 按钮 展开/收起 点击后执行的逻辑
     */
    function setMoreOrLessHandler(approveTaskListGroupItem, index) {
      if (approveTaskListGroupItem.originData.length > approveTaskListGroupItem.children.length) {
        approveTaskListGroupItem.children = approveTaskListGroupItem.originData
      } else {
        approveTaskListGroupItem.children = approveTaskListGroupItem.originData.slice(0, max.value)
      }
      approveTaskListGroupItem.btnText = getBtnText(approveTaskListGroupItem)
      approveTaskListGroup.value[index] = approveTaskListGroupItem
    }
    watch(
        () => props.approveTaskList,
        () => getApproveTaskListGroup(),
        {
          immediate: true
        }
    )
    function getIcon(approveTaskItem: processTaskListItem) {
      const { assignResult, assignUserName } = approveTaskItem
      const picture = import.meta.globEager('../../../../assets/images/*')[
          `../../../../assets/images/${
              assignUserName === t('system') ? 'end' : assignResult?.toLocaleLowerCase()
          }.png`
          ]
      return picture && picture.default ? picture.default : ''
    }
    // 确保在每次更新之前重置ref
    onBeforeUpdate(() => {
      doms.value = []
    })
    return {
      t,
      doms,
      approveTaskListGroup,
      getIcon,
      isNullOrEmpty,
      setMoreOrLessHandler
    }
  }
})
</script>

<style lang="less" scoped>
.approval-history-box {
  overflow: auto;
  padding: 36px 24px 24px 36px;

  & > .title {
    font-size: 16px;
    color: #192842;
    line-height: 60px;
  }

  .start {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #3875ff;
    outline: 2px solid rgba(56, 117, 255, 0.21);
  }

  .avatar {
    width: 27px;
    height: 27px;
    border-radius: 50%;
    line-height: 27px;
    text-align: center;
    font-weight: bold;
    color: #fff;
    font-size: 12px;
    background-color: #3875ff;
  }
  :deep(.@{ant-prefix}-timeline-item-tail) {
    height: 100%;
    border-color: #94b5ff;
  }

  :deep(.@{ant-prefix}-timeline-item-content) {
    font-size: 12px;
  }

  :deep(.@{ant-prefix}-timeline-item) {
    padding-bottom: 0px;

    .@{ant-prefix}-timeline-item-content {
      top: -2px;
    }
    .@{ant-prefix}-timeline-item-head-custom{
      background: rgba(0, 0, 0, 0);
      margin-top: 22px;
    }
  }
  :deep(.@{ant-prefix}-timeline > li.@{ant-prefix}-timeline-item:first-child) {
    .@{ant-prefix}-timeline-item-head-custom{
      background: rgba(0, 0, 0, 0);
      margin-top: 0;
    }
  }

  .approval-history-content {
    padding: 18px 13px;
    background: #f5f5f5;
    border: 1px solid rgba(151, 151, 151, 0.2);
    border-radius: 1px;
    &.end-style{
      background-color: transparent;
      border:0;
    }

    p {
      color: #595959;
      margin: 0;
      line-height: 2em;
    }

    .title {
      font-size: 14px;
      display: flex;
      align-items: center;
      margin: 0;

      .svg-icon,
      i {
        margin-right: 5px;
      }
    }

    .comment {
      font-size: 10px;
      padding-right: 30px;
      word-break: break-all;
    }
  }
}

.status-icon {
  width: 18px;
  height: 18px;
  margin-right: 4px;
}

.group {
  position: relative;

  .group-mark {
    left: -20px;
    height: calc(100% - 16px);
    width: calc(100% + 30px);
    position: absolute;
    border-radius: 5px;
    border: 1px solid #bcc1c8;
    & + div .@{ant-prefix}-timeline-item{
      padding-top: 20px;
      :deep(.@{ant-prefix}-timeline-item-head-custom){
        margin-top: 42px;
      }
    }
  }
  .last-group-child{
    .@{ant-prefix}-timeline-item{
      padding-bottom: 32px;
    }
  }
  .last-group-child-more{
    .@{ant-prefix}-timeline-item{
      padding-bottom: 50px;
    }
  }

  .open {
    position: absolute;
    font-size: 12px;
    color: #3875ff;
    line-height: 36px;
    transform: translate(20px) translateY(-50px);
    display: block;
  }
}
</style>

<i18n>
zh-CN:
  start: 流程开始
  log: 流程日志
  openMore: 展开
  less: 收起
  comment: 留言
  colon: ：
  system: 系统
en-US:
  start: Process start
  log: Process log
  openMore: open
  less: Put away
  comment: Leaving a message.
  colon: ：
  system: System
</i18n>
